package service

import (
	"Todolist/pkg/ctl"
	"Todolist/pkg/utils"
	"Todolist/repository/db/dao"
	"Todolist/repository/db/model"
	"Todolist/types"
	"context"
	"errors"
	"gorm.io/gorm"
	"sync"
)

var UserSrvIns *UserSrv
var UserSrvOnce sync.Once

type UserSrv struct {
}

// 保证了在多线程环境下只实例化一次。这种设计通常用于创建单例模式，确保在整个应用程序的生命周期内只存在一个 UserSrv 的实例。
func GetUserSrv() *UserSrv {
	UserSrvOnce.Do(func() {
		UserSrvIns = &UserSrv{}
	})
	return UserSrvIns
}

// 用户注册逻辑的实现
func (s *UserSrv) UserRegister(ctx context.Context, req *types.UserRegisterReq) (resp interface{}, err error) {
	userDao := dao.NewUserDao(ctx)
	u, err := userDao.FindUserByUserName(req.UserName)
	switch err {
	case gorm.ErrRecordNotFound:
		u = &model.User{
			UserName: req.UserName,
		}
		//密码进行加密存储
		if err = u.SetPassword(req.Password); err != nil {
			utils.LogrusObj.Error(err)
			return
		}

		if err = userDao.CreateUser(u); err != nil {
			utils.LogrusObj.Error(err)
			return
		}
		return ctl.RespSuccess(), nil

	case nil:
		err = errors.New("用户已经存在")
		return
	default:
		return
	}

}

// 传参 穿指针可预防值拷贝
func (s *UserSrv) UserLogin(ctx context.Context, req *types.UserLoginReq) (resp interface{}, err error) {
	userDao := dao.NewUserDao(ctx)
	u, err := userDao.FindUserByUserName(req.UserName)
	if err != nil {
		utils.LogrusObj.Error(err)
		return
	}
	//校验密码
	if !u.CheckPassword(req.Password) {
		err = errors.New("账号/密码错误")
		utils.LogrusObj.Error(err)
		return
	}
	//分发token
	token, err := utils.GenerateToken(u.ID, u.UserName)
	if err != nil {
		utils.LogrusObj.Error(err)
		return
	}
	userResp := types.TokenData{
		User: types.UserLoginResp{
			Id:        u.ID,
			UserName:  u.UserName,
			CreatedAt: u.CreatedAt.Unix(),
		},
		AccessToken: token,
	}

	return ctl.RespSuccessWithData(userResp), nil
}
